import { game } from 'cc';
import { native } from 'cc';

import { am } from '../../scripts/managers/AudioManager';
import { gm } from '../../scripts/managers/GameManager';
import { BaseView } from '../../scripts/libs/rxjs/cc3/BaseView';
import { _decorator, Camera, Node } from 'cc';
import { lastValueFrom, Observable, take } from 'rxjs';
import { udm } from '../../scripts/managers/UserDataManager';
import { nullifySubscription } from '../../scripts/libs/rxjs/utils';
import { linear } from '../../scripts/libs/utils/math';
import { IntervalStartNow, Timer } from '../../scripts/libs/rxjs/cc3/CreatorSchedule';
import { lm } from './LobbyManager';
import { ResType, rm } from '../../scripts/managers/ResourceManager';
import { GameKey } from '../../scripts/managers/SubgameConfig';
import { HotUpdateManager, hum } from '../../scripts/managers/HotUpdateManager';
import { i18n } from '../../scripts/i18n';
import { LoadingPanelMode } from '../../scripts/managers/Enums';
import { uim } from '../../scripts/libs/ui/UIManager';
import { Vec2 } from 'cc';
import { Vec3 } from 'cc';
import { v3 } from 'cc';
import { ResourceHelper } from './ResourceHelper';
import { screen } from 'cc';
import { view } from 'cc';
import { macro } from 'cc';
import { size } from 'cc';
import { sys } from 'cc';
import { ReactiveSet } from '../../scripts/libs/rxjs/cc3/ReactiveSet';
import { Subscription } from 'rxjs';
import { iap_sdk_m } from '../../scripts/managers/SDK/IapSDKManager';
import { misc_sdk_m } from '../../scripts/managers/SDK/MiscSDKManager';
import { applovin_sdk_m } from '../../scripts/managers/SDK/AppLovinCocosSDKManager';
import { thinking_sdk_m } from '../../scripts/managers/SDK/ThinkingCocosSDKManager';
import { DialogPanel } from './ui/DialogPanel/DialogPanel';
import { taskm } from '../../scripts/managers/TaskManager';
import { pfm } from '../../scripts/managers/PlayFabManager';
import { jsb_sdk_m } from '../../scripts/managers/SDK/JsbSDKManager';
const { ccclass, property } = _decorator;

@ccclass('LobbySceneCanvas')
export class LobbySceneCanvas extends BaseView {

    @property(Camera)
    camera: Camera = null;

    @property(Camera)
    cameraBack: Camera = null;

    @property(Node)
    gameRoot: Node = null;

    @property(Node)
    bgNode: Node = null;

    @property(Node)
    node3dContainer: Node = null;

    removeBgReasons = ReactiveSet.Create<string>();

    public get curProgressValue() { return gm.curProgressValue.value }
    public set curProgressValue(v: number) { gm.curProgressValue.value = v; }
    public get maxProgressValue(): number { return gm.maxProgressValue; }

    willBind(): void {
        // 这个游戏就默认关闭背景层
        // this.removeBgReasons.add('default');
    }

    onLoadView() {
        this.log('onLoadView');
        lm.lobbySceneCanvas = this;

        if (udm.fullScreenOn.value) {
            screen.requestFullScreen().then(_ => {
                gm.fullScreenChangedCommand.execute();
            });
        }

        this.delaySetUICameraFront();
    }

    onDestroyView() {
        nullifySubscription.call(this, '_bg_sub');
    }

    _sub_delay_setcamerafront: Subscription = null;
    delaySetUICameraFront() {
        nullifySubscription.call(this, '_sub_delay_setcamerafront');
        if (this.cameraBack != null) {
            this._sub_delay_setcamerafront = IntervalStartNow(.1, this.node).pipe(take(10)).subscribe(_ => {
                this.cameraBack.orthoHeight = this.camera.orthoHeight;
            });
        }
    }

    useObserves() {
        return [
            uim.standby.subscribe(_ => this.log('@@uim.standby', _)),
            this.removeBgReasons.subscribe(_ => {
                this.bgNode.active = this.removeBgReasons.size == 0;
            }),
            // lm.flowStatus.subscribe(flowStatus => {
            //     if (flowStatus == FlowStatus.Room) {
            //         this.removeBgReasons.add('in_room');
            //     } else {
            //         this.removeBgReasons.delete('in_room');
            //     }
            // }),
            // gm.fullScreenChangedCommand.subscribe(_ => {
            //     this.log("@@gm.fullScreenChangedCommand", _);
            //     this.node.getComponentsInChildren(ResizeToVisibleSize).forEach(_ => _.go());
            //     this.node.getComponentsInChildren(FirstResize).forEach(_ => _.go());
            // }),
        ];
    }

    setPortrait() {
        if (sys.isBrowser) {
            if (sys.isMobile) {
                let frameSize = screen.windowSize;
                view.setOrientation(macro.ORIENTATION_PORTRAIT);
                screen.windowSize = size(frameSize.width, frameSize.height);
                let event = document.createEvent("HTMLEvents")
                event.initEvent("orientationchange", true, true)
                window.dispatchEvent(event)
            }
        }
    }

    async start() {

        this.setPortrait();

        let subInterval = IntervalStartNow(.1, this.node).subscribe(_ => {
            if (udm.stageNum.value <= 10) {
                gm.curProgressValue2.value += .5;
            }
        });

        this.curProgressValue = 0;
        lm.loadingAssets.value = true;

        // udm.initialize();

        await lastValueFrom(this.loadItem());

        this.curProgressValue = 100;

        lm.frontTipEnabled.value = true;

        subInterval.unsubscribe();

        lm.loadingAssets.value = false;

        await lastValueFrom(lm.loadingEnabled.whenFalseOnce());
        await lastValueFrom(lm.frontTipReady.whenTrueOnce());
        this.checkHotUpdate();

        this.log('canvas start process over!');
    }

    checkHotUpdate() {
        // resources.load('version', (err, asset) => {
        //     if (err) {
        //         this.log('load version.manifest error', err);
        //         return;
        //     }
        //     this.log('load version.manifest success', asset?._file);
        // });

        hum.startProcess(null, true).subscribe({
            next: _ => {
                let eventCode = _.event.getEventCode();
                if (eventCode === native.EventAssetsManager.NEW_VERSION_FOUND) {
                    let am = _.event.getAssetsManagerEx();
                    let localVersion = am.getLocalManifest().getVersion();
                    let remoteVersion = am.getRemoteManifest().getVersion();
                    // 弹出提示框,让用户确认是否更新
                    DialogPanel.StartProcess(panel => {
                        let dialogPanel = panel as DialogPanel;
                        dialogPanel.content.value = `${i18n.t('lobby.dialogpanel.content_update')}\n${localVersion}->${remoteVersion}`;
                        dialogPanel.title.value = i18n.t('lobby.dialogpanel.title');
                        dialogPanel.okBtnText.value = i18n.t('lobby.dialogpanel.update');
                    }).subscribe(_ => {
                        if (_.result === 'ok') {
                            this.log('user confirm hotupdate');
                            // _.event.getAssetsManagerEx().update();
                            this.startHotUpdate();
                        } else {
                            this.log('user cancel hotupdate');
                            this.afterHotUpdate();
                        }
                    });
                } else if ([native.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST, native.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST, native.EventAssetsManager.ERROR_PARSE_MANIFEST].includes(eventCode)) {
                    // 弹出错误提示框,让用户确认是否更新
                    DialogPanel.StartProcess(panel => {
                        let dialogPanel = panel as DialogPanel;
                        dialogPanel.content.value = `${i18n.t('lobby.dialogpanel.hotupdate_system_error')}\n${HotUpdateManager.EventCodeToString(eventCode)}`;
                        dialogPanel.title.value = i18n.t('lobby.dialogpanel.title');
                        dialogPanel.okBtnText.value = i18n.t('lobby.dialogpanel.retry');
                        dialogPanel.cancelBtnText.value = i18n.t('lobby.dialogpanel.skip');
                    }).subscribe(_ => {
                        if (_.result === 'ok') {
                            this.log('user confirm hotupdate');
                            this.checkHotUpdate();
                        } else {
                            this.log('user cancel hotupdate');
                            this.afterHotUpdate();
                        }
                    });
                }
            },
            complete: () => {
                this.log('hotupdate startProcess complete');
                this.afterHotUpdate();
            }
        });
    }

    startHotUpdate() {
        gm.loadingPanelMode = LoadingPanelMode.Default;
        gm.curProgressValue.value = 0;
        gm.curProgressValue2.value = 0;
        hum.startProcess(null).subscribe({
            next: _ => {
                if (_.event.getEventCode() === native.EventAssetsManager.UPDATE_PROGRESSION) {
                    if (_.event.getAssetsManagerEx().getState() == native.AssetsManager.State.UPDATING) {
                        // 注意此处必须包含这两个条件才能保证进度条的正确显示，只有UPDATE_PROGRESSION这个EventCode是不够的，它还包括两个manifest文件的下载
                        // 而在UPDATING下，就只有游戏资源的下载了
                        this.log('hotupdate update progression', _.event.getPercent(), _.event.getDownloadedBytes(), _.event.getTotalBytes());
                        this.curProgressValue = linear(0, 1, 0, 100, _.event.getPercent());
                        lm.hotupdating.value = true;
                    }
                } else if (_.event.getEventCode() === native.EventAssetsManager.UPDATE_FINISHED) {
                    lm.hotupdating.value = false;
                    Timer(.5).subscribe(_ => {
                        game.restart();
                    });
                } else if ([native.EventAssetsManager.ERROR_UPDATING, native.EventAssetsManager.ERROR_UPDATING].includes(_.event.getEventCode())) {
                    lm.frontTipShow(`${HotUpdateManager.EventCodeToString(_.event.getEventCode())} `);
                }
            },
            complete: () => {
                this.log('hotupdate startProcess complete');
                this.afterHotUpdate();
            }
        });
    }

    afterHotUpdate() {

        thinking_sdk_m.requestTrack('Start_Begin_Game', { isNew: udm.isNew.value });

        pfm.loginWithCustomId(udm.uid.value).subscribe(_ => {
            if (_?.[0]?.code == 200) {
                if (udm.displayName.value == null || pfm.displayName.value == null) {
                    udm.displayName.value = pfm.generatePlayerNumber();
                    pfm.setDisplayName(udm.displayName.value).subscribe();
                    udm.save();
                }
                pfm.updateLeaderboardEntries('stageNum_manual', udm.stageNum.value).subscribe();
            }
        });

        gm.curSubgame.value = GameKey.lobby;

        // misc_sdk_m.requestATA(); // 接入AppsFlyer时，已经请求了
        iap_sdk_m.initialize();

        if (udm.noAds.value == 0) {
            applovin_sdk_m.requestCreateInterstitialAd();
        }
        applovin_sdk_m.requestCreateRewardedAd();

        this.loadAudio();
        this.loadMaterial();

        taskm.refreshStorage();
        taskm.checkInc('login'); // 登录任务

        udm.luckyWheelRefreshStorage();

        jsb_sdk_m.sendMsg('FacebookCocosSDK.getApplicationSignature', "{}");

        // hum.startProcess('ab_subgame001', true).subscribe(_ => {
        //     this.log('subgame001 hotupdate startProcess', _.event.getEventCode());
        // })
    }

    // 加载音频
    loadAudio() {
        rm.loadRes([
            ['ab_lobby/Audio/bgm', ResType.AudioClipDir],
            ['ab_lobby/Audio/sfx', ResType.AudioClipDir],
        ]).subscribe({
            next: _ => {
                this.log('loadAudio result', _);
            },
            complete: () => {
                am.genRootNode('ab_lobby').subscribe({
                    complete: () => {
                        am.bgm.again();
                        am.bgmVolume.value = udm.bgmVolume.value;
                        am.sfxVolume.value = udm.sfxVolume.value;
                    }
                });
                rm.finishedCount.value = 0; // 重置,否则会影响到下次进度条的初始位置
            }
        });
    }


    // 加载通用特效材质
    loadMaterial() {
        rm.loadRes([
            [ResourceHelper.HighlightSingleMaterialPath, ResType.Material],
        ]).subscribe({
            next: _ => {
                this.log('loadMaterial result', _);
            },
            complete: () => {
                rm.finishedCount.value = 0; // 重置,否则会影响到下次进度条的初始位置
                ResourceHelper.CommonMaterialReady.value = true;
            }
        });
    }

    itemCountLoaded = 0;
    public get itemCountMax(): number {
        return 400;
    }

    _loaded_resKeys = new Set<string>();

    loadItem(isPreload = false): Observable<null> {
        let standardStageNum = udm.stageNum.value;
        if (isPreload) standardStageNum = udm.stageNum.value + 1;
        return new Observable(observer => {
            let resList = [];
            if (gm.editEnabled.value) {
                resList.push(...ResourceHelper.ResList);
                resList.push(...ResourceHelper.EditResList);
            } else {
                resList = ResourceHelper.ResList.filter(_ => {
                    if (this._loaded_resKeys.has(_[0] as string)) return false;
                    if (_[2] == null && _[3] == null) return true;
                    if ((_[2] as number) <= standardStageNum) {
                        if (_[3] == null) {
                            return true;
                        } else if (standardStageNum < (_[3] as number)) {
                            return true;
                        }
                    }
                    return false;
                });
            }

            if (isPreload) {
                rm.preloadRes(resList).subscribe({
                    complete: () => {
                        observer.nextAndComplete(null);
                    }
                });
            } else {
                resList.forEach(_ => this._loaded_resKeys.add(_[0]));
                let _sub = rm.loadRes(resList, (finished, total) => {
                    // 单个文件的一部分引用资源加载完了在这里，可以得到更细致的加载进度
                    this.itemCountLoaded++;
                    this.log('loadItem result', this.itemCountLoaded, this.itemCountMax);
                    this.curProgressValue = linear(0, this.itemCountMax, 0, 100, this.itemCountLoaded);
                }).subscribe({
                    next: _ => {
                        // 每个文件夹在完成后在这里
                    },
                    complete: () => {
                        ResourceHelper.PreparePool();
                        rm.finishedCount.value = 0;
                        observer.nextAndComplete(null);
                    }
                });
                return () => {
                    _sub.unsubscribe();
                    _sub = null;
                }
            }
        });
    }

    // 转TouchPosition到WorldPosition
    touchLocationToWorldPosition(location: Vec2, _out?: Vec3) {
        const result = this.camera.screenToWorld(v3(location.x, location.y, 0), _out ?? v3());
        _out.z = 0;
        result.z = 0;
        return result;
    }

}

// console.log('uuid', uuid)

// const { v1: uuidv1, v3: uuidv3, v4: uuidv4, v5: uuidv5 } = uuid;

// // 生成一个基于时间戳和硬件信息的 UUID
// const uuid1 = uuidv1();
// console.log("UUID1:", uuid1);

// // 生成一个基于命名空间和名字的 UUID（MD5）
// const namespace = uuidv3.DNS;
// const name = "example.com";
// const uuid3 = uuidv3(name, namespace);
// console.log("UUID3:", uuid3);

// // 生成一个基于随机数的 UUID
// const uuid4 = uuidv4();
// console.log("UUID4:", uuid4);

// // 生成一个基于命名空间和名字的 UUID（SHA-1）
// const uuid5 = uuidv5(name, namespace);
// console.log("UUID5:", uuid5);

// console.log('myUUID:', uuidv5(uuidv1(), uuidv4()));